package com.bugsnag.ohos;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;

/**
 * JsonStream
 *
 * @since 2021-07-27
 */
public class JsonStream extends JsonWriter {
    private final ObjectJsonStreamer objectJsonStreamer;
    private final Writer out;

    /**
     * Streamable
     *
     * @since 2021-07-27
     */
    public interface Streamable {
        /**
         * to stream
         *
         * @param writer
         * @throws IOException
         */
        void toStream(JsonStream writer) throws IOException;
    }

    /**
     * Constructs a JSONStream
     *
     * @param out the writer
     */
    public JsonStream(Writer out) {
        super(out);
        setSerializeNulls(false);
        this.out = out;
        objectJsonStreamer = new ObjectJsonStreamer();
    }

    /**
     * name to json stream
     *
     * @param name the name of the forthcoming value. May not be null.
     * @return json stream
     * @throws IOException
     */
    public JsonStream name(String name) throws IOException {
        super.name(name);
        return this;
    }

    /**
     * Serialises an arbitrary object as JSON, handling primitive types as well as
     * Collections, Maps, and arrays.
     *
     * @param object
     * @param shouldRedactKeys
     * @throws IOException
     */
    public void value(Object object, boolean shouldRedactKeys) throws IOException {
        if (object instanceof Streamable) {
            ((Streamable) object).toStream(this);
        } else {
            objectJsonStreamer.objectToStream(object, this, shouldRedactKeys);
        }
    }

    /**
     * Serialises an arbitrary object as JSON, handling primitive types as well as
     * Collections, Maps, and arrays.
     *
     * @param object
     * @throws IOException
     */
    public void value(Object object) throws IOException {
        value(object, false);
    }

    /**
     * Writes a File (its content) into the stream
     *
     * @param file
     * @throws IOException
     */
    public void value(File file) throws IOException {
        if (file == null || file.length() <= 0) {
            return;
        }
        super.flush();
        beforeValue();
        Reader input = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            input = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
            IoUtils.copy(input, out);
        } finally {
            IoUtils.closeQuietly(input);
        }
        out.flush();
    }
}
